package com.cqupt.tr.component.filter;


import com.cqupt.tr.Utils.*;
import com.cqupt.tr.bean.BaseMessage;
import com.cqupt.tr.component.JwtTokenUtils;
import com.cqupt.tr.login.service.UserDetailsServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.web.authentication.WebAuthenticationDetailsSource;
import org.springframework.stereotype.Component;
import org.springframework.web.filter.OncePerRequestFilter;
import redis.clients.jedis.Jedis;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;

@Component
public class JWTAuthorizationFilter extends OncePerRequestFilter {

    @Autowired
    private UserDetailsServiceImpl userDetailsService;

    @Autowired
    private RedisUtils redisUtils;

    @Override
    protected void doFilterInternal(HttpServletRequest request,
                                    HttpServletResponse response,
                                    FilterChain chain) throws IOException, ServletException {

//        String tokenHeader = request.getHeader(JwtTokenUtils.TOKEN_HEADER);
//        // 如果请求头中没有Authorization信息则直接放行了
//        if (tokenHeader == null || !tokenHeader.startsWith(JwtTokenUtils.TOKEN_PREFIX)) {
//            chain.doFilter(request, response);
//            return;
//        }
//        // 如果请求头中有token，则进行解析，并且设置认证信息
//        SecurityContextHolder.getContext().setAuthentication(getAuthentication(tokenHeader));
//        super.doFilterInternal(request, response, chain);

        Jedis jedis = redisUtils.getJedis();
        BaseMessage baseMessage = new BaseMessage();
        try {
            String authHeader = request.getHeader("Authorization");
            //获取请求的ip地址
            String currentip = AccessAddressUtil.getIpAddress(request);//不能直接getRemoteAddr()，因为反向代理

            if(authHeader!=null&&authHeader.startsWith("Bearer ")) {
                String authtoken = authHeader.substring(7);
                String username = JwtTokenUtils.getUsername(authtoken);
                String ip = CollectionUtil.getMapValue(JwtTokenUtils.getClaims(authtoken), "ip");
                String role = CollectionUtil.getMapValue(JwtTokenUtils.getClaims(authtoken), "role");
                String blacklist = jedis.hget("blacklist", authtoken);
                if (blacklist != null ) {
                    if(!blacklist.equals("")){

                        baseMessage.setCode("0");
                        baseMessage.setMsg("再黑名单中，拒绝访问");
                        baseMessage.setData("fail");
                        response.getWriter().write(ObjectJsonTransFunction.toJsonStr(baseMessage));
                        return;
                    }

                }
                //判断token是否过期
                /*
                 * 过期的话，从redis中读取有效时间（比如七天登录有效），再refreshToken（根据以后业务加入，现在直接refresh）
                 * 同时，已过期的token加入黑名单
                 */
               ;
                if (jedis.exists(authtoken)) {
                    //判断redis是否保存
                    String expirationTime = jedis.hget(authtoken, "expirationTime").toString();
                    if(JwtTokenUtils.isExpirationWithTime(expirationTime)){
                        String tokenValidTime = jedis.hget(authtoken, "tokenValidTime");
                        String currentTime = DateUtil.getTime();
                        jedis.hset("blacklist",authtoken,currentTime);

                        if(DateUtil.compareDate(currentTime,tokenValidTime)){
                            //超过有效期，不刷新
                            baseMessage.setCode("0");
                            baseMessage.setMsg("surpass time");
                            response.getWriter().write(ObjectJsonTransFunction.toJsonStr(baseMessage));
                            return;
                        }else{
//                            String usernameByToken = JwtTokenUtils.getUsername(authtoken);
//                            username = usernameByToken;
//                            ip = jedis.hget(authtoken,"ip");
//                            role = jedis.hget(authtoken,"role");

                            Map<String, Object> map = new HashMap<>();
                            map.put("ip",ip);
                            map.put("role",role);
                            String jwtToken = JwtTokenUtils.createToken(username, map, false);
                            Integer expire = 30 * 60;
                            jedis.hset(jwtToken,"tokenValidTime",DateUtil.getAddDaySecond(60*30));
                            jedis.hset(jwtToken,"expirationTime",DateUtil.getAddDaySecond(300));
                            jedis.hset(jwtToken,"username",username);
                            jedis.hset(jwtToken,"role",role);
                            jedis.hset(jwtToken,"ip",ip);
                            jedis.hset(jwtToken,"userauth",ObjectJsonTransFunction.toJsonStr(jedis.hget(authtoken,"userauth")));
                            jedis.expire(jwtToken,expire);
                            //删除旧token
                            jedis.del(authtoken);
                            authtoken = jwtToken;
                            response.setHeader("Authorization", "Bearer " + jwtToken);

                        }
                    }
                }
                if(username!=null&& SecurityContextHolder.getContext().getAuthentication() == null){
                    //判断ip  暂留
                    UserDetails userDetails = userDetailsService.loadUserByUsername(username);
                    if(userDetails!=null){
                        UsernamePasswordAuthenticationToken authentication =
                                new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities());
                        authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));

                        SecurityContextHolder.getContext().setAuthentication(authentication);
                    }

                }

            }
            chain.doFilter(request,response);
            }catch (Exception e){
            e.printStackTrace();
                baseMessage.setMsg("re login");
                baseMessage.setCode("0");
                baseMessage.setData("fail to login");
            response.getWriter().write(ObjectJsonTransFunction.toJsonStr(baseMessage));
             }finally {
            jedis.close();
           }


    }

    // 这里从token中获取用户信息并新建一个token
    private UsernamePasswordAuthenticationToken getAuthentication(String tokenHeader) {
        String token = tokenHeader.replace(JwtTokenUtils.TOKEN_PREFIX, "");
        Map<String, Object> claims = JwtTokenUtils.getClaims(token);
        String role = claims.get("rol").toString();
        String username = JwtTokenUtils.getUsername(token);
        if(username==null|| username.equals("")) return null;
        else{
            return new UsernamePasswordAuthenticationToken(username, null, Collections.singleton(new SimpleGrantedAuthority(role)));
        }

    }
}
